home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / getloadavg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-20  |  18.8 KB  |  727 lines

  1. /*
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of M.I.T. not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  M.I.T. makes no representations about the
  11.  * suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  16.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  18.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  19.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  20.  *
  21.  * Authors:  Many and varied...
  22.  */
  23.  
  24. #ifndef lint
  25. static char sccs_id[] = "%W%";
  26. static char  rcsid[] = "@(#)$Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
  27. #endif /* !lint */
  28.  
  29. #include "conf.h"
  30.  
  31. /* Necessary as AIX has a typedef for syserr [err.c] in sysinfo.h */
  32. #ifndef _AIX
  33. # include "sendmail.h"
  34. #endif /* !_AIX */
  35.  
  36. #ifdef DGUX
  37. # include <sys/dg_sys_info.h>
  38.  
  39. int getloadavg( call_data )
  40.      caddr_t    call_data;    /* pointer to (double) return value */
  41. {    
  42.     struct dg_sys_info_load_info load_info;
  43.  
  44.     dg_sys_info(&load_info,
  45.         DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
  46.  
  47.     *(double *)call_data = load_info.one_minute;
  48. }
  49. #else /* DGUX */
  50.  
  51. # ifdef UMAX
  52. /*
  53.  *
  54.  *    FOR: Encore multimax UMAX 4.3.
  55.  *
  56.  *    Extracted from get_stats() (written by John Robert LoVerso)
  57.  *    by Neil Rickert.
  58.  *
  59.  *    Use inq_stats() to determine boottime, load average
  60.  *
  61.  */
  62.  
  63. #  include <sys/param.h> /* */
  64. #  include <inq_stats/statistics.h>
  65. #  include <inq_stats/procstats.h>
  66.  
  67. /*
  68.  * see dimension of ps_nrun[] in procstats.h
  69.  */
  70. #  ifndef PS_NRUNSIZE
  71. #   define PS_NRUNSIZE 300
  72. #  endif
  73.  
  74. /*
  75.  * Each entry in ps_nrun[] is count of runnable processes sampled every
  76.  * 5 seconds.  period[] contains the number of samples to use for the
  77.  * intervals of {1,5,15} minutes.  cexp[] contains constans for exponential
  78.  * decay.
  79.  */
  80. #  define period 12
  81.  
  82. int getloadavg( call_data )
  83.      caddr_t    call_data;    /* pointer to (double) return value */
  84. {
  85.     struct stat_descr    Proc_info;
  86.     struct proc_summary    Proc_sum_data;
  87.     register int i, index, interval;
  88.  
  89.     /*
  90.      * struct to get process summary data,
  91.      * esp circular buffer containing counts of runnable processes
  92.      */
  93.     Proc_info.sd_next = NULL;
  94.     Proc_info.sd_subsys = SUBSYS_PROC;
  95.     Proc_info.sd_type = PROCTYPE_SUMMARY;
  96.     Proc_info.sd_addr = (char *) &Proc_sum_data;
  97.     Proc_info.sd_size = sizeof (struct proc_summary);
  98.     Proc_info.sd_sizeused = 0;
  99.  
  100.     /*
  101.      * fill in Boot_data and Proc_sum_data structures
  102.      */
  103.     if (inq_stats(1, &Proc_info) != 0) {
  104. #  ifdef LOG
  105.         syslog(LOG_WARNING, "getloadavg: inq_stats(): %m");
  106. #  endif /* LOG */
  107.         return (-1);
  108.     }
  109.  
  110.     /*
  111.      * fastest (inverse shared sum) loop
  112.      */
  113.     index = Proc_sum_data.ps_nrunidx;
  114.     interval = 0;
  115.     *(double *)call_data = 0.0;
  116.     for (; interval < period; interval++) {
  117.         *(double *)call_data += Proc_sum_data.ps_nrun[index];
  118.         if (--index < 0)
  119.             index = PS_NRUNSIZE-1;
  120.         }
  121.  
  122.         *(double *)call_data /= period;
  123. }
  124. # else /* UMAX */
  125.  
  126. #  ifdef _AIX
  127. /*
  128.  * This version of this module (get_load.c) is specifically for the IBM
  129.  * S/6000 AIX 3.1 platform. The copyright below applies to this module
  130.  * only.
  131.  *
  132.  * Copyright (C) 1990 by the University of Illinois Board of Trustees.
  133.  *
  134.  * This code is distributed in the hope that it will be useful,
  135.  * but without any warranty.  No author or distributor accepts
  136.  * responsibility to anyone for the consequences of using it or for
  137.  * whether it serves any particular purpose or works at all, unless
  138.  * s/he says so in writing.
  139.  *
  140.  * Author: Charley Kline, University of Illinois Computing Services
  141.  *         c-kline@uiuc.edu
  142.  *
  143.  */
  144.  
  145. #   include <sys/sysinfo.h>
  146. #   include <unistd.h>
  147. #   include <fcntl.h>
  148. #   include <syslog.h>
  149. #   include <math.h>
  150. #   include <nlist.h>
  151.  
  152. struct nlist kernelnames[] = {
  153.     {"sysinfo", 0, 0, 0, 0, 0},
  154.     {NULL, 0, 0, 0, 0, 0},
  155. };
  156.  
  157.  
  158. /* ARGSUSED */
  159. int 
  160. getloadavg (call_data)
  161.     caddr_t  call_data;    /* pointer to (double) return value */
  162. {
  163.     double *loadavg = (double *)call_data;
  164.     double   loadav;
  165.     static double avenrun = 0.;
  166.     struct sysinfo si;
  167.     static int rq_old = 0, ro_old = 0;
  168.     static   initted = 0;
  169.     static int fd;
  170.     double   multiplier;
  171.     double   t;
  172.  
  173.     /*
  174.      * * Do stuff we only need to do once per invocation, like opening *
  175.      * the kmem file and fetching the parts of the symbol table.
  176.      */
  177.     if (!initted) {
  178.         initted = 1;
  179.         knlist (kernelnames, 1, sizeof (struct nlist));
  180.         if ((fd = open ("/dev/kmem", O_RDONLY)) < 0)
  181.         {
  182. #   ifdef LOG
  183.             syslog(LOG_WARNING, "getloadavg: open /dev/kmem: %m");
  184. #   endif /* LOG */
  185.             return (-1);
  186.         }
  187.     }
  188.     /*
  189.      * * Get the system info structure from the running kernel.
  190.      */
  191.     lseek (fd, kernelnames[0].n_value, SEEK_SET);
  192.     if (read (fd, (char *)&si, sizeof (struct sysinfo)) != sizeof (struct sysinfo))
  193.     {
  194. #   ifdef LOG
  195.             syslog(LOG_WARNING, "getloadavg: read /dev/kmem: %m");
  196. #   endif /* LOG */
  197.             return (-1);
  198.     }
  199.  
  200.     /*
  201.      * AIX doesn't keep the load average variables in the kernel; all
  202.      * we can get is the current number of runnable processes by
  203.      * observing the difference between the runque and runocc values in
  204.      * sysinfo. Having done this, however, we can apply a TENEX-style
  205.      * exponential time-average to it by computing an averaging multiplier
  206.      * based on the sampling interval. This is then used to factor in *
  207.      * the current number of running processes to our running load
  208.      * average. The result "looks right" when observed in conjunction
  209.      * with the process table and user activity.
  210.      * 
  211.      * We subtract one from the number of running processes given us by
  212.      * the kernel because for some reason AIX always calls one of the
  213.      * kernel processes "runnable" even though it uses very little CPU.
  214.      * Subtracting this out gives a load average near zero when the
  215.      * machine is mostly idle, which is more familiar to those of us who
  216.      * are used to bsd-style load averages.
  217.      */
  218.     t = (double) (si.runocc - ro_old);
  219.     loadav = (double) (si.runque - rq_old) / t - 1.0;
  220.     rq_old = si.runque;
  221.     ro_old = si.runocc;
  222.     multiplier = exp (-t / 60.);
  223.     avenrun = multiplier * avenrun + (1.0 - multiplier) * loadav;
  224.     /*
  225.      * DEBUG printf("%d %d %f %f %f\n", si.runque, si.runocc, t, loadav,
  226.      * avenrun);
  227.      */
  228.  
  229.     *loadavg = avenrun;
  230.     return (0);
  231. }
  232. #  else /* !_AIX */
  233.  
  234. /*
  235.  * Get open(2) constants
  236.  */
  237. #   ifdef SYSV
  238. #    ifndef macII
  239. #     include <fcntl.h>
  240. #    endif /* !macII */
  241. #   endif /* SYSV */
  242. #   include <sys/file.h>
  243. #   ifdef USG
  244. #    include <unistd.h>
  245. #   endif /* USG */
  246.  
  247. #   ifdef att
  248. #    define LOADSTUB
  249. #   endif /* att */
  250.  
  251. #   ifdef apollo
  252. #    include <apollo/base.h>
  253. #    include <apollo/time.h>
  254. #    ifdef notdef
  255. typedef struct {
  256.     short        state;        /* ready, waiting, etc. */
  257.     pinteger    usr;        /* user sr */
  258.     linteger    upc;        /* user pc */
  259.     linteger    usp;        /* user stack pointer */
  260.     linteger    usb;        /* user sb ptr (A6) */
  261.     time_$clock_t    cpu_total;    /* cumulative cpu used by process */
  262.     unsigned short    priority;    /* process priority */
  263.     } proc1_$info_t;
  264.  
  265. /*  Enable function prototypes for ANSI C and C++  */
  266. #     if (defined(__STDC__) || defined(c_plusplus) || defined(__cplusplus)) \
  267.     && !defined(__GNUC__)
  268. #      define _PROTOTYPES
  269. #     endif /* (__STDC__ || c_plusplus || __cplusplus) && !__GNUC__ */
  270.  
  271. void proc1_$get_cput(
  272. #     ifdef _PROTOTYPES
  273.     time_$clock_t    *cput
  274. #     endif /* _PROTOTYPES */
  275. );
  276.  
  277. void proc1_$get_info(
  278. #     ifdef _PROTOTYPES
  279.     short        &pid,
  280.     proc1_$info_t    *info,
  281.     status_$t    *sts
  282. #     endif /* _PROTOTYPES */
  283. );
  284. #     ifdef _PROTOTYPES
  285. #      undef _PROTOTYPES
  286. #     endif /* _PROTOTYPES */
  287.  
  288. #    endif /* notdef */
  289. #   endif /* apollo */
  290.  
  291. #   if !defined(macII) && !defined(apollo) && !defined(LOADSTUB)
  292. #    include <nlist.h>
  293. #   endif /* !macII && !apollo && !LOADSTUB */
  294.  
  295. #   ifdef sun
  296. #    include <sys/param.h>
  297. #    ifdef i386
  298. #     include <kvm.h>
  299. #     define    KVM_ROUTINES
  300. #    endif /* i386 */
  301. #   endif /* sun */
  302.  
  303. #   if defined(mips) && !defined(sgi)
  304. #    include <sys/fixpoint.h>
  305. #   endif /* mips && !sgi */
  306.  
  307. #   ifdef CRAY
  308. #    include <sys/param.h>
  309. #    include <sys/sysinfo.h>
  310. #    undef n_type
  311. #    define n_type n_value
  312. #   endif /* CRAY */
  313.  
  314. #   ifdef vax
  315. #    include <sys/param.h>
  316. #   endif /* vax */
  317.  
  318. #   ifdef sequent
  319. #    include <sys/vm.h>
  320. #   endif /* sequent */
  321.  
  322. #   ifdef macII
  323. #    include <a.out.h>
  324. #    include <sys/var.h>
  325. #    define X_AVENRUN 0
  326. #    define fxtod(i) (vec[i].high+(vec[i].low/65536.0))
  327. struct lavnum {
  328.     unsigned short high;
  329.     unsigned short low;
  330. };
  331. #   endif /* macII */
  332.  
  333. #   ifdef unixpc
  334. #    define FSCALE    64.0
  335. #   endif /* unixpc */
  336.  
  337. #   if defined(UTEK) || defined(alliant)
  338. #    define FSCALE    100.0
  339. #   endif /* UTEK || alliant */
  340.  
  341. #   if (defined(sequent) || defined(NeXT) || defined(sgi)) && !defined(FSCALE)
  342. #    define FSCALE    1000.0
  343. #   endif /* (sequent || NeXT || sgi) && !FSCALE */
  344.  
  345. #   ifdef hp9000
  346. #    include <sys/param.h>
  347. #   endif /* hp9000 */
  348.  
  349. #   ifndef FSCALE
  350. #    define    FSHIFT    8    /* bits to right of fixed binary point */
  351. #    define    FSCALE    (1<<FSHIFT)
  352. #   endif /* !FSCALE */
  353.  
  354. #   ifdef __STDC__
  355. extern off_t lseek(int, off_t, int);
  356. extern void exit(int);
  357. #   else /* !__STDC__ */
  358. extern long lseek();
  359. extern void exit();
  360. #   endif /* __STDC__ */
  361.  
  362. #   if apollo
  363. /* ARGSUSED */
  364. int getloadavg( call_data )
  365.      caddr_t    call_data;    /* pointer to (double) return value */
  366. {
  367. #    ifdef notdef
  368.      static int     firstTime = 1;
  369.      static int     lastNullCpu;
  370.      static int     lastClock;
  371.      time_$clock_t  timeNow;
  372.      double         temp;
  373.      proc1_$info_t  info;
  374.      status_$t      st;
  375.  
  376.      proc1_$get_info( (short) 2, &info, &st );
  377.      time_$clock( &timeNow );
  378.  
  379.      if (firstTime)
  380.      {
  381.          *(double *)call_data = 1.0;
  382.          firstTime = 0;
  383.      }
  384.      else {
  385.          temp = info.cpu_total.low32 - lastNullCpu;
  386.          *(double *)call_data = 1.0 - temp / (timeNow.low32 - lastClock);
  387.      }
  388.  
  389.      lastClock = timeNow.low32;
  390.      lastNullCpu = info.cpu_total.low32;
  391.      return(0);
  392. #    else /* !notdef */
  393.      double *avenrun = (double *) call_data;
  394.      int i;
  395.      status_$t      st;
  396.      long loadav[3];
  397.      proc1_$get_loadav(loadav, &st);
  398.      *avenrun = loadav[0] / (double) (1 << 16);
  399.      return(0);
  400. #    endif /* notdef */
  401. }
  402. #   else /* !apollo */
  403. #    ifdef KVM_ROUTINES
  404. /*
  405.  *    Sun 386i Code - abstracted to see the wood for the trees
  406.  */
  407.  
  408. /* ARGSUSED */
  409. void 
  410. getloadavg( call_data )
  411.      caddr_t    call_data;    /* pointer to (double) return value */
  412. {
  413.     double *loadavg = (double *)call_data;
  414.     long    temp;
  415.     static int init = 0;
  416.     static struct nlist nl[2];
  417.     static kvm_t *kd;
  418.     
  419.     if (!init) {
  420.     kd = kvm_open("/vmunix", NULL, NULL, O_RDONLY, NULL);
  421.     if (kd == (kvm_t *)0) {
  422. #    ifdef LOG
  423.         syslog(LOG_WARNING, "getloadavg: kvm_open /vmunix: %m");
  424. #    endif /* LOG */
  425.         return (-1);
  426.     }
  427.     
  428.     nl[0].n_name = "avenrun";
  429.     nl[1].n_name = NULL;
  430.     
  431.     if (kvm_nlist(kd, nl) != 0) {
  432. #    ifdef LOG
  433.         syslog(LOG_WARNING, "getloadavg: kvm_nlist /vmunix: %m");
  434. #    endif /* LOG */
  435.         return (-1);
  436.     }
  437.     init = 1;
  438.     }
  439.     
  440.     if (nl[0].n_value == 0) {
  441.         return (-1);
  442.     }
  443.     if (kvm_read(kd, nl[0].n_value, (char *)&temp, sizeof (temp)) != 
  444.     sizeof (temp)) {
  445. #    ifdef LOG
  446.         syslog(LOG_WARNING, "getloadavg: kvm_read /vmunix: %m");
  447. #    endif /* LOG */
  448.     return (-1);
  449.     }
  450.     *loadavg = (double)temp/FSCALE;
  451.     return(0);
  452. }
  453. #    else /* !KVM_ROUTINES */
  454. #     ifdef LOADSTUB
  455.  
  456. /* ARGSUSED */
  457. int getloadavg( call_data )
  458.      caddr_t    call_data;    /* pointer to (double) return value */
  459. {
  460.     *(double *)call_data = 1.0;
  461. }
  462.  
  463. #     else /* !LOADSTUB */
  464.  
  465. #      ifndef KMEM_FILE
  466. #       define KMEM_FILE "/dev/kmem"
  467. #      endif /* !KMEM_FILE */
  468.  
  469. #      ifndef KERNEL_FILE
  470.  
  471. #       ifdef NeXT
  472. #        define KERNEL_FILE "/mach"
  473. #       endif /* NeXT */
  474.  
  475. #       ifdef alliant
  476. #        define KERNEL_FILE "/unix"
  477. #       endif /* alliant */
  478.  
  479. #       ifdef CRAY
  480. #        define KERNEL_FILE "/unicos"
  481. #       endif /* CRAY */
  482.  
  483. #       ifdef hpux
  484. #        define KERNEL_FILE "/hp-ux"
  485. #       endif /* hpux */
  486.  
  487. #       ifdef macII
  488. #        define KERNEL_FILE "/unix"
  489. #       endif /* macII */
  490.  
  491. #       ifdef mips
  492. #        ifdef SYSTYPE_SYSV
  493. #         define KERNEL_FILE "/unix"
  494. #        else /* !SYSTYPE_SYSV */
  495. #         define KERNEL_FILE "/vmunix"
  496. #        endif /* SYSTYPE_SYSV */
  497. #       endif /* mips */
  498.  
  499. #       ifdef sequent
  500. #        define KERNEL_FILE "/dynix"
  501. #       endif /* sequent */
  502.  
  503. /*
  504.  * provide default for everyone else
  505.  */
  506. #       ifndef KERNEL_FILE
  507. #        ifdef SYSV
  508. #         define KERNEL_FILE "/unix"
  509. #        else /* !SYSV */
  510. #         define KERNEL_FILE "/vmunix"
  511. #        endif /* SYSV */
  512. #       endif /* KERNEL_FILE */
  513. #      endif /* KERNEL_FILE */
  514.  
  515. #      ifndef KERNEL_LOAD_VARIABLE
  516. /*
  517.  * provide default
  518.  */
  519. #       ifdef USG
  520. #        define KERNEL_LOAD_VARIABLE "sysinfo"
  521. #        define SYSINFO
  522. #       else /* !USG */
  523. #        define KERNEL_LOAD_VARIABLE "_avenrun"
  524. #       endif /* USG */
  525.  
  526. #       ifdef alliant
  527. #        undef KERNEL_LOAD_VARIABLE
  528. #        define KERNEL_LOAD_VARIABLE "_Loadave"
  529. #       endif /* alliant */
  530.  
  531. #       ifdef CRAY
  532. #        if defined(CRAY2) && OSMAJORVERSION == 4
  533. #         undef KERNEL_LOAD_VARIABLE
  534. #         define KERNEL_LOAD_VARIABLE "avenrun"
  535. #        else /* !CRAY2 || OSMAJORVERSION != 4 */
  536. #         undef KERNEL_LOAD_VARIABLE
  537. #         define KERNEL_LOAD_VARIABLE "sysinfo"
  538. #         define SYSINFO
  539. #        endif /* CRAY2 && OSMAJORVERSION == 4 */
  540. #       endif /* CRAY */
  541.  
  542. #      ifdef hpux
  543. #       ifdef hp9000s800
  544. #        undef KERNEL_LOAD_VARIABLE
  545. #        define KERNEL_LOAD_VARIABLE "avenrun"
  546. #       endif /* hp9000s800 */
  547. #      endif /* hpux */
  548.  
  549. #      ifdef mips
  550. #       ifdef SYSTYPE_SYSV
  551. #        undef KERNEL_LOAD_VARIABLE
  552. #        define KERNEL_LOAD_VARIABLE "avenrun"
  553. #       else /* !SYSTYPE_SYSV */
  554. #        undef KERNEL_LOAD_VARIABLE
  555. #        define KERNEL_LOAD_VARIABLE "_avenrun"
  556. #       endif /* SYSTYPE_SYSV */
  557. #      endif /* mips */
  558.  
  559. #      ifdef unixpc
  560. #       undef KERNEL_LOAD_VARIABLE
  561. #       define KERNEL_LOAD_VARIABLE "avenrun"
  562. #      endif /* unixpc */
  563. #     endif /* KERNEL_LOAD_VARIABLE */
  564.  
  565. #     ifdef macII
  566. struct var v;
  567. static int pad[2];    /* This padding is needed if getloadavg compiled on */
  568.             /* a/ux 1.1 is executed on a/ux 1.0, because */
  569.             /* the var structure had too much padding in 1.0, */
  570.             /* so the 1.0 kernel writes past the end of the 1.1 */
  571.             /* var structure in the uvar() call. */
  572. static struct nlist nl[2];
  573. static struct lavnum vec[3];
  574. #     else /* not macII */
  575. static struct nlist namelist[] = {        /* namelist for vmunix grubbing */
  576. #      define LOADAV 0
  577. #      ifdef NeXT
  578.     {{KERNEL_LOAD_VARIABLE}},
  579.     {{0},0}
  580. #      else /* !NeXT */
  581. #       ifdef unixpc
  582.     { KERNEL_LOAD_VARIABLE, },
  583.     { (char *)0, },
  584. #       else /* !unixpc */
  585.     {KERNEL_LOAD_VARIABLE},
  586.     {0}
  587. #       endif /* unixpc */
  588. #      endif /* NeXT */
  589. };
  590. #     endif /* macII */
  591.  
  592.  
  593. /* ARGSUSED */
  594. int getloadavg( call_data )
  595.      caddr_t    call_data;    /* pointer to (double) return value */
  596. {
  597.       double *loadavg = (double *)call_data;
  598.     static int init = 0;
  599.     static kmem;
  600.     static long loadavg_seek;
  601. #     ifdef macII
  602. #      ifdef __STDC__
  603.         extern int nlist(const char *, struct nlist *);
  604. #      else /* !__STDC__ */
  605.         extern int nlist();
  606. #      endif /* __STDC__ */
  607.  
  608.         if(!init)   {
  609.             int i;
  610.  
  611.             (void) strcpy(nl[0].n_name, "avenrun");
  612.             nl[1].n_name[0] = '\0';
  613.  
  614.             kmem = open(KMEM_FILE, O_RDONLY);
  615.             if (kmem < 0) {
  616. #     ifdef LOG
  617.             syslog(LOG_WARNING, "getloadavg: open %s: %m", KMEM_FILE);
  618. #     endif /* LOG */
  619.         return (-1);
  620.         }
  621.  
  622.             uvar(&v);
  623.  
  624.             if (nlist( KERNEL_FILE, nl) != 0) {
  625. #     ifdef LOG
  626.             syslog(LOG_WARNING, "getloadavg: nlist %s: %m", KERNEL_FILE);
  627. #     endif /* LOG */
  628.         return (-1);
  629.         }
  630.             for (i = 0; i < 2; i++) {
  631.                 nl[i].n_value = (int)nl[i].n_value - v.v_kvoffset;
  632.             }
  633.             init = 1;
  634.         }
  635. #     else /* !macII */
  636. #      ifdef unixpc
  637. #       ifdef __STDC__
  638.         extern int nlist(const char *, struct nlist *);
  639. #       else /* !__STDC__ */
  640.         extern int nlist();
  641. #       endif /* __STDC__ */
  642.  
  643.     if (!init)
  644.     {
  645.         if (nlist(KERNEL_FILE, namelist) != 0)
  646.             return (-1);
  647.         loadavg_seek = (long)namelist[0].n_value;
  648.         if ((kmem = open(KMEM_FILE, O_RDONLY)) < 0)
  649.             return (-1);
  650.         init = 1;
  651.         }
  652. #      else /* !unixpc */
  653. #       if !defined(sgi) && !defined(BSD4_4)
  654.     extern void nlist();
  655. #       else /* sgi || BSD4_4 */
  656.     extern nlist();
  657. #       endif /* !sgi && !BSD4_4 */
  658.  
  659.     if(!init)   {
  660.         nlist( KERNEL_FILE, namelist);
  661. /*
  662.  * Some systems appear to set only one of these to Zero if the entry could
  663.  * not be found, I hope no_one returns Zero as a good value, or bad things
  664.  * will happen to you.  (I have a hard time believing the value will
  665.  * ever really be zero anyway).   CDP 5/17/89.
  666.  */
  667.         if (namelist[LOADAV].n_type == 0 ||
  668.         namelist[LOADAV].n_value == 0) {
  669.         return (-1);
  670.         }
  671.         loadavg_seek = namelist[LOADAV].n_value;
  672. #       if defined(mips) && defined(SYSTYPE_SYSV)
  673.         loadavg_seek &= 0x7fffffff;
  674. #       endif /* mips && SYSTYPE_SYSV */
  675. #       if defined(CRAY) && defined(SYSINFO)
  676.          loadavg_seek += ((char *) (((struct sysinfo *)NULL)->avenrun)) -
  677.                         ((char *) NULL);
  678. #       endif /* CRAY && SYSINFO */
  679.  
  680.         kmem = open(KMEM_FILE, O_RDONLY);
  681.         if (kmem < 0) {
  682. #       ifdef LOG
  683.             syslog(LOG_WARNING, "getloadavg: open %s: %m", KMEM_FILE);
  684. #       endif /* LOG */
  685.         return (-1);
  686.         }
  687.         init = 1;
  688.     }
  689. #      endif /* unixpc */
  690.     (void) lseek(kmem, loadavg_seek, 0);
  691. #     endif /* macII */
  692. #     if defined(sun) || defined (UTEK) || defined(sequent) || \
  693.       defined(alliant) || defined(hp9000) || defined(sgi) || defined(NeXT) || \
  694.       defined(unixpc)
  695.     {
  696.         long temp;
  697.         (void) read(kmem, (char *)&temp, sizeof(long));
  698.         *loadavg = (double)temp/FSCALE;
  699.     }
  700. #     else /* !sun && !UTEK && !sequent && !alliant && !hp9000 && !sgi && !NeXT && !unixpc */
  701. #      ifdef macII
  702.         {
  703.                 lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
  704.                 read(kmem, vec, 3*sizeof(struct lavnum));
  705.                 *loadavg = fxtod(0);
  706.         }
  707. #      else /* !macII */
  708. #       if defined(mips)
  709.     {
  710.         fix temp;
  711.         (void) read(kmem, (char *)&temp, sizeof(fix));
  712.         *loadavg = FIX_TO_DBL(temp);
  713.     }
  714. #       else /* !mips */
  715.     (void) read(kmem, (char *)loadavg, sizeof(double));
  716. #        endif /* mips */
  717. #       endif /* macII */
  718. #      endif /* sun || UTEK || sequent || alliant || hp9000 || sgi || NeXT || unixpc */
  719.     return(0);
  720. }
  721. #     endif /* LOADSTUB */
  722. #    endif /* KVM_ROUTINES */
  723. #   endif /* apollo */
  724. #  endif /* _AIX */
  725. # endif /* UMAX */
  726. #endif /* DGUX */
  727.